package com.groupbuying.settleproducer.service.impl;

import com.groupbuying.settleproducer.connector.SysconfigFeign;
import com.groupbuying.settleproducer.connector.YSFeign;
import com.groupbuying.settleproducer.constants.*;
import com.groupbuying.settleproducer.domain.SettleUshopFlowStoreDO;
import com.groupbuying.settleproducer.domain.SettleUshopWithdrawalDO;
import com.groupbuying.settleproducer.domain.SettleUshopWithdrawalYsFirstClearDO;
import com.groupbuying.settleproducer.dto.YSBalanceAccountDetailDTO;
import com.groupbuying.settleproducer.dto.YSBalanceReturnDTO;
import com.groupbuying.settleproducer.dto.YSWithdrawalFirstDTO;
import com.groupbuying.settleproducer.dto.YSWithdrawalQueryDTO;
import com.groupbuying.settleproducer.service.*;
import com.groupbuying.settleproducer.utils.DateUtils;
import com.groupbuying.settleproducer.utils.JsonUtils;
import com.groupbuying.settleproducer.utils.apiresult.ApiResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: WANGNING
 * @Email wyn20140226@aliyun.com
 * @Date: 2019/8/29 17:35
 * @Des 一清+余额提现
 */
@Service
public class SettleUshopFirstClearAndBalanceServiceImpl implements SettleUshopFirstClearAndBalanceService {
    public static final Logger logger = LoggerFactory.getLogger(SettleUshopFirstClearAndBalanceServiceImpl.class);
    @Autowired
    private SettleUshopFlowStoreService settleUshopFlowStoreService;
    @Autowired
    private YSFeign ysFeign;
    @Autowired
    private SysconfigFeign sysconfigFeign;
    @Autowired
    private SettleUshopWithdrawalYsFirstClearService withdrawalYsFirstClearService;
    @Autowired
    private SettleUshopWithdrawalService settleWithdrawalService;
    @Autowired
    private SettleUshopBalancePaymentService settleUshopBalancePaymentService;
    @Autowired
    private SettleUshopIntegralPaymentService settleUshopIntegralPaymentService;
    @Override
    public ApiResult firstClearAndBalance(Map<String, Object> map) {
        logger.info("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()------>一清+余额提现从商户中心获取到的map信息:" + map.toString());
        // 解析map参数---商户号（门店id）
        Object tempParam = map.get("storeUuid");
        String counterId = tempParam == null ? null : tempParam.toString();
        // 解析map参数---提现总金额
        tempParam = map.get("totalAmount");
        String allPrice = tempParam == null ? null : tempParam.toString();
        BigDecimal allPriceStr = new BigDecimal(allPrice);
        //获取提现id（从商户中心获取）
        tempParam = map.get("withdrawalId");
        String withdrawalId = tempParam == null ? null : tempParam.toString();
        //获取商户账户余额（从商户中心获取）
        tempParam = map.get("totalAcountAmount");
        String totalAcountAmount = tempParam == null ? null : tempParam.toString();
        BigDecimal totalAcount = new BigDecimal(totalAcountAmount);
        // 解析map参数---商户生成的订单号
        // 解析map参数---币种--CNY
        String currency = SettleUshopYSWithdrawalQueryEnumConstants.ENUM_CURRENCY_CNY;
        // 解析map参数---订单说明
        tempParam = map.get("subject");
        String subject = tempParam == null ? null : tempParam.toString();
        // 解析map参数---银盛报备商户号
        tempParam = map.get("ysUserCode");
        String merchantUsercode = tempParam == null ? null : tempParam.toString();
        // 解析map参数---商户日期
        String shopdate = DateUtils.format(new Date(), "yyyyMMdd");
        /*------------提现金额类型--------------*/
        // 解析map参数---现金提现金额
        tempParam = map.get("cashAmount");
        String cashAmountStr = tempParam == null ? null : tempParam.toString();
        BigDecimal cashAmount = new BigDecimal(cashAmountStr);
        // 解析map参数---余额提现金额
        tempParam = map.get("balanceAmount");
        String balanceAmountStr = tempParam == null ? null : tempParam.toString();
        BigDecimal balanceAmount = new BigDecimal(balanceAmountStr);
        /*-----------获取该商户的银行卡信息---------*/
        // 解析map参数---银行名称
        tempParam = map.get("bankName");
        String bankName = tempParam == null ? null : tempParam.toString();
        // 解析map参数---开户行所在城市
        tempParam = map.get("cityName");
        String cityName = tempParam == null ? null : tempParam.toString();
        // 解析map参数---银行帐号
        tempParam = map.get("bankAccountNo");
        String bankAccountNo = tempParam == null ? null : tempParam.toString();
        // 解析map参数---银行帐号用户名
        tempParam = map.get("bankAccountName");
        String bankAccountName = tempParam == null ? null : tempParam.toString();
        // 解析map参数---收款方银行账户类型corporate :对公账户;personal:对私账户
        tempParam = map.get("bankAccountType");
        String bankAccountType = tempParam == null ? null : tempParam.toString();
        // 解析map参数---支持卡类型debit:借记卡;credit:信用卡 unit:单位结算卡
        tempParam = map.get("bankCardType");
        String bankCardType = tempParam == null ? null : tempParam.toString();
        // 解析map参数---获取积分金额(判断积分是否记录)
        tempParam = map.get("integralAmount");
        String integralAmountStr = tempParam == null ? null : tempParam.toString();
        //判断请求参数不为空
        if (StringUtils.isEmpty(counterId)
                || StringUtils.isEmpty(currency) || StringUtils.isEmpty(subject)
                || StringUtils.isEmpty(shopdate) || StringUtils.isEmpty(bankAccountNo)
                || StringUtils.isEmpty(totalAcountAmount)) {
            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance() failure!------>银盛一清提现-----请求参数为空，请检查" );
            return ApiResult.paramIsNull();
        }
        try {
            /*初始化对象*/
            int withdrawalYsFirstClearStatus;
            /*调用银盛提现*/
            String withdrawalReal;
            /*提现状态*/
            int settleWithdrawalStatus;
            SettleUshopWithdrawalYsFirstClearDO withdrawalYsFirstClear = new SettleUshopWithdrawalYsFirstClearDO();
            SettleUshopFlowStoreDO settleUshopFlowStoreDO = new SettleUshopFlowStoreDO();
            YSWithdrawalFirstDTO ysWithdrawalFirstDTO = new YSWithdrawalFirstDTO();
            /*判断是否有余额支付状态初始化*/
            Boolean balanceStatus =false;
            /*判断是否有余额支付状态初始化*/
            Boolean integralStatus =false;
            BigDecimal accountAmount;
            //判断提现金额---提现的现金部分的金额对比
            if (cashAmount.compareTo(totalAcount) <= 0) {
                //请求银盛提现接口
                /*生成随机数4位*/
                String mathString = String.valueOf((int)((Math.random()*9+1)*1000));
                String outTradeNo = DateUtils.format(new Date(), "yyyyMMdd") + counterId + mathString;
                ysWithdrawalFirstDTO.setBank_account_no(bankAccountNo);
                ysWithdrawalFirstDTO.setCurrency(currency);
                ysWithdrawalFirstDTO.setOut_trade_no(outTradeNo);
                ysWithdrawalFirstDTO.setShopdate(shopdate);
                ysWithdrawalFirstDTO.setSubject(subject);
                ysWithdrawalFirstDTO.setTotal_amount(cashAmount);
                ysWithdrawalFirstDTO.setMerchant_usercode(merchantUsercode);
                String ysWithdrawalJSON = JsonUtils.toJSon(ysWithdrawalFirstDTO);
                Map<String, Object> ysSplitReceiptMap = new ConcurrentHashMap<String, Object>();
                Map<String, Object> balanceMap = new HashMap<String, Object>();
                Map<String, Object> condMap = new HashMap<String, Object>();
                ysSplitReceiptMap.put("biz_content", ysWithdrawalJSON);
                //查询银盛商户余额
                balanceMap.put(SettleWithdrawalSearchConstants.MERCHANT_USERCODE, merchantUsercode);
                condMap.put("biz_content", JsonUtils.toJSon(balanceMap));
                logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----调用银盛查询余额之前的biz_content："+ condMap.get("biz_content"));
                String balanceJson = this.ysFeign.balanceQuery(condMap);
                logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----调用银盛查询余额返回json字符串为："+ balanceJson);
                //解析返回来的余额json
                YSBalanceReturnDTO ysBalanceReturnDTO = (YSBalanceReturnDTO) JsonUtils.convertBean(balanceJson, YSBalanceReturnDTO.class);
                List<YSBalanceAccountDetailDTO> balanceAccountDetailList = ysBalanceReturnDTO.getAccount_detail();
                String accountAmounts = balanceAccountDetailList.get(0).getAccount_amount();
                accountAmount = new BigDecimal(accountAmounts);
                logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----银盛返回一般商户余额为："+ accountAmount);
                //获取手续费
                String fees = this.sysconfigFeign.getFeeCash();
                BigDecimal feeCash = new BigDecimal(fees);
                logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()----商户提现金额："+ allPriceStr+"  银盛可提现金额："+ accountAmount+"  平台手续费："+feeCash);
                if (accountAmount.compareTo(cashAmount.add(feeCash)) >= 0) {
                    //调用银盛提现------方可提现
                    withdrawalReal = ysFeign.withdrawal(ysSplitReceiptMap);
                    logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----调用银盛一清提现返回json："+ withdrawalReal);
                    //判断银盛返回状态码code
                    Map<String ,Object> withdrawalRealMap= JsonUtils.jsonToMap(withdrawalReal);
                    String returnCode=(String)withdrawalRealMap.get("code");
                    if(returnCode.equalsIgnoreCase(SettleWithdrawalEnumConstants.ENUM_WITHDRAWALCODE_SUC)){
                        //解析返回来参数信息
                        String outTradeNos = (String) withdrawalRealMap.get("out_trade_no");
                        String subMsg = (String) withdrawalRealMap.get("sub_msg");
                        String msg = (String) withdrawalRealMap.get("msg");
                        String code = (String) withdrawalRealMap.get("code");
                        String tradeStatus = (String) withdrawalRealMap.get("trade_status");
                        String totalAmount = (String) withdrawalRealMap.get("total_amount");
                        String partnerFee = (String) withdrawalRealMap.get("partner_fee");
                        String payeeFee = (String) withdrawalRealMap.get("payee_fee");
                        String payerFee = (String) withdrawalRealMap.get("payer_fee");
                        //判断请求参数不为空
                        if (StringUtils.isEmpty(outTradeNos) && StringUtils.isEmpty(tradeStatus) && StringUtils.isEmpty(totalAmount)
                                && StringUtils.isEmpty(partnerFee) && StringUtils.isEmpty(payeeFee) && StringUtils.isEmpty(payerFee)) {
                            return ApiResult.failure(Integer.parseInt(code), msg, subMsg);
                        }
                        //生成总表提现记录初始化
                        SettleUshopWithdrawalDO settleWithdrawal = new SettleUshopWithdrawalDO();
                        settleWithdrawal.setId(withdrawalId);
                        settleWithdrawal.setCounterId(counterId);
                        settleWithdrawal.setTotalPrice(new BigDecimal(totalAcountAmount));
                        settleWithdrawal.setWithdrawalPrice(allPriceStr);
                        settleWithdrawal.setWithdrawalType(SettleWithdrawalEnumConstants.ENUM_WITHDRAWALTYPE_FIRST);
                        String serviceFee = this.sysconfigFeign.getFeeCash();
                        settleWithdrawal.setServiceFee(new BigDecimal(serviceFee));
                        settleWithdrawal.setPaycompanyBalance(accountAmount);
                        settleWithdrawal.setWithdrawalState(SettleWithdrawalEnumConstants.ENUM_WITHDRAWALSTATE_WAIT);
                        settleWithdrawal.setGmtCreate(new Date());
                        settleWithdrawal.setGmtModified(new Date());
                        settleWithdrawal.setIsDelete(SettleWithdrawalEnumConstants.ENUM_ISDELETE_UNDEL);
                        settleWithdrawalStatus =settleWithdrawalService.save(settleWithdrawal);
                        /*生成一清金额子表信息*/
                        withdrawalYsFirstClear.setCounterId(counterId);
                        withdrawalYsFirstClear.setWithdrawalId(withdrawalId);
                        withdrawalYsFirstClear.setSplitState(WithdrawalYsFirstClearEnumConstants.ENUM_SPLITSTATE_SUC);
                        withdrawalYsFirstClear.setWithdrawalPrice(cashAmount);
                        withdrawalYsFirstClear.setGmtCreate(new Date());
                        withdrawalYsFirstClear.setGmtModified(new Date());
                        withdrawalYsFirstClear.setIsDelete(SettleWithdrawalEnumConstants.ENUM_ISDELETE_UNDEL);
                        withdrawalYsFirstClearStatus =withdrawalYsFirstClearService.save(withdrawalYsFirstClear);
                        logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----一清提现子表数据保存成功！");
                        if(!balanceAmountStr.equalsIgnoreCase("0")){
                            balanceStatus = settleUshopBalancePaymentService.createBalancePayment(map);
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----余额代付银盛返回boolean值为:"+balanceStatus);
                        }else{
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----余额代付银盛返回false,改变余额代付存在问题，相对应的out_trade_no为："+outTradeNo);
                        }
                        /*判断是否有积分支付---生成积分子表*/
                        if(!integralAmountStr.equalsIgnoreCase("0")){
                            integralStatus = settleUshopIntegralPaymentService.createIntegralPayment(map);
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----积分代付银盛返回boolean值为:"+integralStatus);
                        }else{
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----积分代付银盛返回false,改变积分代付存在问题，相对应的out_trade_no为："+outTradeNo);
                        }
                        /*生成提现总表信息*/
                        if( balanceStatus|| integralStatus && withdrawalYsFirstClearStatus>0){
                            /*插入一条提现记录到分账商户子表中--提现金额（混合支付总和）为负数*/
                            settleUshopFlowStoreDO.setAmount(allPriceStr.multiply(new BigDecimal("-1")));
                            settleUshopFlowStoreDO.setStoreId(counterId);
                            settleUshopFlowStoreDO.setExternalId(withdrawalId);
                            settleUshopFlowStoreDO.setGmtCreate(new Date());
                            settleUshopFlowStoreDO.setGmtModified(new Date());
                            settleUshopFlowStoreDO.setIsDelete(SettleWithdrawalEnumConstants.ENUM_ISDELETE_UNDEL);
                            settleUshopFlowStoreDO.setFlowType(SettleUshopFlowStoreEnumConstants.ENUM_FLOWTYPE_WITHDRAWAL);
                            settleUshopFlowStoreDO.setNote(SettleUshopFlowStoreEnumConstants.ENUM_WITHDRAWAL_NODE);
                            settleUshopFlowStoreDO.setId(sysconfigFeign.getFlowId());
                            settleUshopFlowStoreDO.setCheckstandId("27002");
                            this.settleUshopFlowStoreService.save(settleUshopFlowStoreDO);
                            /*通知store中心方可提现，更改总表提现记录为成功提现*/
                            settleWithdrawal.setWithdrawalState(SettleWithdrawalEnumConstants.ENUM_WITHDRAWALSTATE_SUC);
                            this.settleWithdrawalService.update(settleWithdrawal);
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----商户一清+余额/积分流水表数据保存成功！-----更改提现总表提现状态为成功");
                            //调通知商户同步余额状态
                            Map<String, Object> withdrawalMap = notifyStoreAccount(counterId, allPrice, withdrawalId);
                            /*描述*/
                            withdrawalMap.put("description", String.format(StoreFlowDescription.WITHDRAWAL_SUCC, withdrawalId, allPrice));
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----通知商户中心更改资金变动情况，数据是："+withdrawalMap.toString());
                            return ApiResult.success(withdrawalMap);
                        }else{
                            settleWithdrawal.setWithdrawalState(SettleWithdrawalEnumConstants.ENUM_WITHDRAWALSTATE_FAIL);
                            this.settleWithdrawalService.update(settleWithdrawal);
                            //通知商户同步余额状态
                            Map<String, Object> withdrawalMap = notifyStoreAccount(counterId, allPrice, withdrawalId);
                            /*描述------积分/余额提现失败*/
                            withdrawalMap.put("description", String.format(StoreFlowDescription.ENUM_NOTICESTORE_BALANCEANDINTEGRAL,allPrice,balanceStatus,integralStatus));
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()------一清现金提现或者余额代付失败！对应的支付单号："+outTradeNo+"对应的余额代付返回值是："+balanceStatus+"对应的积分代付返回值是:"+integralStatus);
                            return ApiResult.failure(withdrawalMap);
                        }

                    }else{
                        //提现失败，调用提现查询接口，返回信息
                        try {
                            Map<String, Object> withdrawalMap = new HashMap<>();
                            YSWithdrawalQueryDTO ysWithdrawalQueryDTO = new YSWithdrawalQueryDTO();
                            ysWithdrawalQueryDTO.setOut_trade_no(outTradeNo);
                            ysWithdrawalQueryDTO.setShopdate(shopdate);
                            String ysWithdrawalJson = JsonUtils.beanToJson(ysWithdrawalQueryDTO);
                            withdrawalMap.put("biz_content", ysWithdrawalJson);
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----请求银盛提现查询之前biz_content数据为："+withdrawalMap.get("biz_content"));
                            String withdrawalJson = ysFeign.withdrawalQuery(withdrawalMap);
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-----请求银盛提现查询返回数据json："+withdrawalJson);
                            //return ApiResult.success(withdrawalJson);
                            //通知商户同步余额状态
                            Map<String, Object> withdrawal = notifyStoreAccount(counterId, allPrice, withdrawalId);
                            /*描述*/
                            withdrawalMap.put("description", String.format(StoreFlowDescription.WITHDRAWAL_FAIL, withdrawalId, allPrice));
                            return ApiResult.failure((Integer)(JsonUtils.jsonToMap(withdrawalJson)).get("code"), (String)(JsonUtils.jsonToMap(withdrawalJson)).get("msg"), withdrawalJson);
                        } catch (Exception e) {
                            e.printStackTrace();
                            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()-->createFirstWithdrawalQuery fail e:", e);
                        }
                    }
                }else{
                    //通知商户同步余额状态
                    Map<String, Object> withdrawalMap = notifyStoreAccount(counterId, allPrice, withdrawalId);
                    /*描述*/
                    withdrawalMap.put("description", String.format(StoreFlowDescription.WITHDRAWAL_FAIL, withdrawalId, allPrice));
                    logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()", "您提现的金额是:"+allPrice+"银盛提现金额不足,银盛账户有:"+accountAmount+"，账户没有足够的可提现金额!");
                    return ApiResult.failure(SettleWithdrawalEnumConstants.ENUM_WITHDRAWALCODE_FAIL, String.format(StoreFlowDescription.ENUM_NOTICESTORE_YSPLATFORM, allPrice, accountAmount), withdrawalMap);
                }
            }else{
                //通知商户同步余额状态
                Map<String, Object> withdrawalMap = notifyStoreAccount(counterId, allPrice, withdrawalId);
                /*描述*/
                withdrawalMap.put("description", String.format(StoreFlowDescription.WITHDRAWAL_FAIL, withdrawalId, allPrice));
                logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance()", "您提现的金额是:"+allPrice+",平台账户有:"+totalAcountAmount+",账户没有足够的可提现金额,请重新填写!");
                return ApiResult.failure(SettleWithdrawalEnumConstants.ENUM_WITHDRAWALCODE_FAIL,  String.format(StoreFlowDescription.ENUM_NOTICESTORE_PLATFORM, allPrice, totalAcountAmount), withdrawalMap);
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            logger.error("SettleUshopFirstClearAndBalanceServiceImpl.firstClearAndBalance() fail e:", e);
        }

        return ApiResult.failure();
    }
    //通知商户中心资金变动-----异常
    private Map<String, Object> notifyStoreAccount(String counterId, String allPrice, String withdrawalId) {
        //调用商户的feign接口通知商户同步余额状态
        Map<String, Object> withdrawalMap = new ConcurrentHashMap<>();
        /*商户提现金额*/
        withdrawalMap.put("operFreezeAmount", allPrice);
        /*支付单号*/
        withdrawalMap.put("orderNo", withdrawalId);
        /*商户账号*/
        withdrawalMap.put("storeUuid", counterId);
        /*业务类型*/
        withdrawalMap.put("businessType", SettleWithdrawalEnumConstants.ENUM_BUSINESS_WITHDRAWAL);
        /*金额标识--支出*/
        withdrawalMap.put("operType", SettleWithdrawalEnumConstants.ENUM_FREEZE_MONEY);
        /*商户会员号(待定--目前是商户号)*/
        withdrawalMap.put("customerUuid", counterId);
        return withdrawalMap;
    }
}
